<template>
  <div class="user-model">
    <el-dialog
      v-model="commonStore.isShowModel"
      :title="isEditModel ? modelConfig.title.editTitle : modelConfig.title.addNewTitle"
      width="30%"
      center
      destroy-on-close
      :close-on-click-modal="false"
    >
      <div class="model-form">
        <el-form
          ref="formRef"
          :model="formData"
          :rules="modelConfig.rules"
          :label-width="modelConfig.labelWidth ?? '100'"
          :label-position="modelConfig.labelPosition ?? 'right'"
          :size="modelConfig.size ?? 'large'"
        >
          <template v-for="item in modelConfig.formItems" :key="item.prop">
            <!-- input -->
            <template v-if="item.type === 'input'">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-input v-model.trim="formData[item.prop]" :placeholder="item.placeholder" />
              </el-form-item>
            </template>

            <!-- input (password) -->
            <template v-if="item.type === 'password' && !isEditModel">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-input
                  type="password"
                  v-model.trim="formData[item.prop]"
                  :placeholder="item.placeholder"
                  show-password
                />
              </el-form-item>
            </template>

            <!-- select -->
            <template v-if="item.type === 'select' && (isHideMenuItem || item.prop !== 'hide')">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-select
                  style="width: 100%"
                  v-model.trim="formData[item.prop]"
                  :placeholder="item.placeholder"
                  @change="seletItem(item)"
                >
                  <template v-for="option in item.options" :key="option.value">
                    <el-option :label="option.label" :value="option.value" />
                  </template>
                </el-select>
              </el-form-item>
            </template>

            <!-- costom -->
            <template v-if="item.type === 'custom'">
              <el-form-item :label="item.label" :prop="item.prop">
                <slot :name="item.slotName"></slot>
              </el-form-item>
            </template>

            <!-- switch -->
            <template v-if="item.type === 'switch'">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-switch
                  class="ml-2"
                  style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
                  v-model="formData[item.prop]"
                  :active-value="1"
                  :inactive-value="0"
                  :before-change="handleBeforeSwitchChange"
                  @change="handleSwitchChange(formData[item.prop])"
                />
              </el-form-item>
            </template>

            <!--upload-->
            <template v-if="item.type === 'upload'">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-upload
                  class="avatar-uploader"
                  action="#"
                  :show-file-list="false"
                  :before-upload="handleBeforeUpload"
                  :http-request="handleUpload"
                >
                  <img v-if="formData[item.prop]" :src="formData[item.prop]" class="avatar" />

                  <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
                </el-upload>
              </el-form-item>
              <p style="margin: 10px 0 0 100px">{{ item.tip }}</p>
            </template>

            <!-- select -->
            <template v-if="item.type === 'menu' && !isHideMenuItem2">
              <el-form-item :label="item.label" :prop="item.prop">
                <el-select
                  style="width: 100%"
                  v-model.trim="formData[item.prop]"
                  :placeholder="item.placeholder"
                >
                  <template v-for="option in item.options" :key="option.id">
                    <el-option :label="option.name" :value="option.id" />
                  </template>
                </el-select>
              </el-form-item>
            </template>
          </template>
        </el-form>
      </div>

      <template #footer>
        <div class="model-footer">
          <el-button @click="hiddenModel">取消</el-button>
          <el-button type="primary" @click="handleConfirmClick">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import useSystemStore from '@/stores/main/system/system'
import { ElMessage, type FormInstance } from 'element-plus'
import { ref, reactive, watch } from 'vue'
import { isCode } from '@/utils/iscode'
import { postUploadImageApi } from '@/service/api'
import type { IModelConfig } from './type'
import useCommonStore from '@/stores/main/common/common'

// - props
const props = defineProps<{
  modelConfig: IModelConfig
  modelOtherData?: object
  pageName: string
}>()
// - store
const systemStore = useSystemStore()
const commonStore = useCommonStore()
// - data
const formRef = ref<FormInstance>()
const isEditModel = ref(false)
const editItem = ref()
const formData = reactive<any>({})

const isHideMenuItem = ref<boolean>(false)
const isHideMenuItem2 = ref<boolean>(true)
watch(formData, (value) => {
  if (props.pageName == 'system/menu') {
    if (value.menuType == 1) {
      value.hide = ''
      isHideMenuItem.value = false
      isHideMenuItem2.value = true
    } else if (value.menuType == 2) {
      isHideMenuItem.value = true
      isHideMenuItem2.value = false
    } else if (value.menuType == 3) {
      value.hide = ''
      isHideMenuItem.value = false
      isHideMenuItem2.value = false
    }
  }
})
// - emit
const emit = defineEmits(['updatePageData', 'related'])

// - methods
const handleConfirmClick = () => {
  // 合并其他表单数据
  let submitData: any = formData

  if (props.modelOtherData) submitData = { ...formData, ...props.modelOtherData }

  formRef.value?.validate((valid) => {
    if (valid) {
      if (isEditModel.value) {
        submitData.id = editItem.value.id
        systemStore
          .editPageDataAction(props.pageName + '/update', { ...submitData })
          .then((res) => {
            if (isCode(res, true)) {
              hiddenModel()
              emit('updatePageData')
            }
          })
      } else {
        systemStore.addNewPageDataAction(props.pageName + '/add', { ...submitData }).then((res) => {
          if (isCode(res, true)) {
            hiddenModel()
            emit('updatePageData')
          }
        })
      }
    }
  })
}
//启用、停止状态
const switchState = reactive({
  switchStatus: false // 用于解决el-switch初始化会执行change事件
})

const handleBeforeSwitchChange = () => {
  switchState.switchStatus = true
  return switchState.switchStatus
}
const handleSwitchChange = (item) => {
  if (switchState.switchStatus) {
  }
}
const showModel = (isEdit, payload?: any, isRelated?: boolean) => {
  isEditModel.value = isEdit

  if (isEdit && payload) {
    // 编辑
    for (const key in formData) {
      formData[key] = payload[key]
    }
    editItem.value = payload
  } else {
    // 新增
    for (const key in formData) {
      const findItem = props.modelConfig.formItems.find((item) => item.prop === key)

      formData[key] =
        findItem?.initialValue || findItem?.initialValue == 0 ? findItem.initialValue : ''
    }
    editItem.value = null
  }
  if (!isRelated) {
    setTimeout(() => {
      commonStore.isShowModel = true
    }, 100)
  }
}
const hiddenModel = () => {
  formRef.value?.resetFields()
  commonStore.isShowModel = false
}

//选择下拉
const seletItem = (item: any) => {
  if (item.related) {
    if (formData[item.related]) {
      formData[item.related] = ''
    }
    emit('related', formData[item.prop])
  }
}

//上传文件
const handleBeforeUpload = (rawFile) => {
  if (rawFile.size / 1024 / 1024 > 5) {
    ElMessage.error('picture size can not exceed 5MB!')
    return false
  }
  return true
}

const handleUpload = async (rawFile: any) => {
  let form = new FormData()
  form.append('file', rawFile.file)
  let res = await postUploadImageApi(form)
  if (isCode(res)) {
    props.modelConfig.formItems.map((item: any) => {
      if (item.prop == 'icon') {
        formData.icon = res.result.url
      } else if (item.prop == 'imgUrl') {
        formData.imgUrl = res.result.url
      } else if (item.prop == 'img') {
        formData.img = res.result.url
      }
    })
  }
}

// - init fn
const init = () => {
  // 初始化formData
  for (const item of props.modelConfig.formItems) {
    formData[item.prop] = ''
  }
}
init()

// - expose
defineExpose({ showModel })
</script>

<style lang="less" scoped>
.user-model {
  .model-form {
    padding: 0 30px 0 20px;

    .el-form-item {
      margin: 0;
      padding: 15px 0;
      word-break: keep-all;
      .el-input {
        max-width: 500px;
      }
    }
  }

  .model-footer {
    display: flex;
    justify-content: flex-end;
    padding: 0 35px;

    .el-button {
      padding: 0 20px;
    }
  }
}
</style>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>
